import {
  CMEVENTS,
  CommandDialog,
  DesignTable,
  FeatureManager,
  getQueryParam,
  ObjInfo,
  QueryParamKeys,
  S3Inst,
  StringUtils,
  Types,
} from '@amcax/base';
import { CommandFormFooter } from '@app-cad/common/components/command-form/footer';
import { ctx2, userEvents } from '@app-cad/module';
import { CurvedBaseCommand, FeaturedCmdDialogParams } from '@app-cad/types';
import {
  Button,
  Checkbox,
  Col,
  Input,
  Modal,
  Progress,
  Radio,
  Row,
  Spin,
  Tabs,
  TabsProps,
  Tooltip,
} from 'antd';

import { MessageTip } from '@app-cad/common/utils/MessageTip';
import { CheckboxChangeEvent } from 'antd/es/checkbox';
import i18n from 'i18next';
import { ChangeEvent, useEffect, useMemo, useRef, useState } from 'react';
import { Cell, Column, HeaderCell, Table } from 'rsuite-table';
import { SingleSelectList } from '../../components/SingleSelectList';
import { ColumnParameterLinkage } from './ColumnParameterLinkage';
import { CsvFileImporter } from './CsvFileImporter';
import { DesignTableEditor } from './DesignTableEditor';
import { useTableConfiguration } from './hooks';
import { ParameterTransfer } from './ParameterTransfer';
import { DesignTableColumn, Parameter } from './types';

import { DESIGN_TABLE_EVENTS } from '@app-base/common/Constants';
import 'rsuite-table/dist/css/rsuite-table.css';
import './index.scss';
import { httpApi } from '@app-base/server';

export type DesignTableStage = 'creation' | 'configuration';
export type DesignTypeMode = 'create' | 'import';

function DesignTableCommand({
  title,
  onClose,
  props,
}: FeaturedCmdDialogParams) {
  const {
    commandCenters: { designTableCommands },
    docMgr,
  } = ctx2;

  const [loading, setLoading] = useState(true);
  const [parameters, setParameters] = useState<Parameter[]>([]);

  const isConfiguration = props?.type === Types.DESIGN_TABLE_CONFIGURATION;
  const designTableDocObj = (isConfiguration
    ? props.parent
    : props) as unknown as ObjInfo;

  const [mode, setMode] = useState<DesignTypeMode>('create');
  const isImportMode = useMemo(() => mode === 'import', [mode]);

  // states for table
  const [tableId, setTableId] = useState<string>();
  const [tableName, setTableName] = useState('设计表');
  const [designTable, setDesignTable] = useState<DesignTable>();

  const stage = useMemo<DesignTableStage>(
    () => (designTable ? 'configuration' : 'creation'),
    [designTable],
  );

  // state for the parameter transfer component
  const [targetKeys, setTargetKeys] = useState<string[]>([]);

  useEffect(() => {
    setTableId(designTableDocObj?.dxid);
    setTableName(designTableDocObj?.label || '设计表');
    setDesignTable(designTableDocObj?.table);
  }, [designTableDocObj]);

  const { columns, configurationDataSource, linkedColumns, unlinkedColumns } =
    useTableConfiguration(designTable, parameters);

  // states for linking parameters to design table columns
  const [selectedParameter, setSelectedParameter] = useState('');
  const [selectedColumnIndex, setSelectedColumnIndex] = useState(-1);
  const [selectedColumns, setSelectedColumns] = useState<number[]>([]);

  const fileInputRef = useRef<HTMLInputElement>(null);
  const [fileToImport, setFileToImport] = useState<File | null>(null);
  const [showProgress, setShowProgress] = useState(false);
  const [uploadPercent, setUploadPercent] = useState(0);
  const [activeTabKey, setActiveTabKey] = useState('paramConfig');
  const [editorOpen, setEditorOpen] = useState(false);
  const [selectedConfigRow, setSelectedConfigRow] = useState<number>();

  useEffect(() => {
    designTableCommands
      .getPartParameter()
      .then((params: Parameter[]) => {
        setParameters(params);
        setLoading(false);
      })
      .catch((err: any) => {
        MessageTip.error(err?.message || '获取参数失败');
        setLoading(false);
      });

    const abortController = new AbortController();

    window.addEventListener(
      'keydown',
      (e: KeyboardEvent) => {
        e.stopPropagation();

        if (e.key === 'Escape') {
          onClose();
        }
      },
      abortController,
    );

    (window as any)?.electronCenter?.on(
      DESIGN_TABLE_EVENTS.SET_DESIGN_TABLE_ID,
      (id) => {
        setTableId(id);
      },
    );

    return () => {
      abortController.abort();
      (window as any)?.electronCenter?.off(
        DESIGN_TABLE_EVENTS.SET_DESIGN_TABLE_ID,
      );
    };
  }, []);

  useEffect(() => {
    const abortController = new AbortController();

    if (tableId) {
      userEvents.on(
        CMEVENTS.DOCUMENTS_CHANGE,
        () => {
          const tableObject = docMgr.getDocumentObjectById(tableId);

          if (tableObject) {
            setTableName(tableObject.label);
            setDesignTable(tableObject.table);
          }
        },
        abortController.signal,
      );
    }

    return () => abortController.abort();
  }, [tableId, docMgr.flatDocumentObjects]);

  useEffect(() => {
    // for the import file button in the configuration stage
    if (fileToImport && stage === 'configuration' && tableId) {
      importFromCsv(tableId).then(async () => {
        await docMgr.updateDocumentObjects();
        setFileToImport(null);
        setActiveTabKey('paramConfig');
      });
    }
  }, [fileToImport, stage, tableId]);

  const linkParameter = async () => {
    try {
      await designTableCommands.linkDesignTableCol(
        tableId,
        selectedColumnIndex as number,
        selectedParameter as string,
      );
      setSelectedParameter('');
      setSelectedColumnIndex(-1);
    } catch (err: any) {
      MessageTip.error(err?.message || '参数关联失败');
    }
  };

  const unlinkParameters = async () => {
    try {
      await Promise.all(
        selectedColumns.map((index) =>
          designTableCommands.unlinkDesignTableCol(tableId, index),
        ),
      );
      setSelectedColumns([]);
    } catch (err: any) {
      MessageTip.error(err?.message || '取消关联失败');
    }
  };

  const tabItems: TabsProps['items'] = [
    {
      label: '参数配置',
      key: 'paramConfig',
      children: (
        <div className='w-[750px] h-[280px]'>
          <Tooltip
            title='双击数据行使用该行数据进行参数配置'
            placement='right'
          >
            <Table
              className='design-table-configuration'
              data={configurationDataSource}
              fillHeight
              width={750}
              rowHeight={36}
              headerHeight={36}
              bordered
              cellBordered
              rowClassName={(_rowData, rowIndex) =>
                `${rowIndex !== -1 && rowIndex === designTable?.configuration ? 'used-configuration-row' : ''}`
              }
              onRowClick={({ seqNum }) => {
                setSelectedConfigRow(seqNum - 1);
              }}
            >
              {columns.map((col) => (
                <Column
                  key={col.dataKey}
                  fixed={col.fixed || false}
                  align='left'
                  width={col.width}
                  resizable={col.resizable !== false}
                >
                  <HeaderCell>{col.title}</HeaderCell>
                  <Cell
                    dataKey={col.dataKey}
                    onDoubleClick={async () => {
                      if (
                        selectedConfigRow !== null &&
                        selectedConfigRow >= 0
                      ) {
                        try {
                          await designTableCommands.activeDesignTableRow(
                            tableId,
                            selectedConfigRow,
                          );
                          await docMgr.updateDocumentObjects();
                        } catch (err: any) {
                          MessageTip.error(
                            err?.message || '使用行数据配置参数失败',
                          );
                        }
                      }
                    }}
                  />
                </Column>
              ))}
            </Table>
          </Tooltip>
        </div>
      ),
    },
    {
      label: '参数关联',
      key: 'paramLink',
      children: (
        <Row gutter={[16, 16]}>
          <Col>
            <div>模型参数</div>
            <SingleSelectList<Parameter, string>
              items={parameters.filter(
                (p) => !designTable?.keys?.includes?.(p?.key),
              )}
              selectedKey={selectedParameter}
              onSelect={setSelectedParameter}
              getKey={(item) => item.key}
              renderItem={(item) => item.label}
            />
          </Col>
          <Col>
            <div>设计表列</div>
            <SingleSelectList<DesignTableColumn, number>
              items={unlinkedColumns}
              selectedKey={selectedColumnIndex}
              onSelect={setSelectedColumnIndex}
              getKey={(item) => item.key}
              renderItem={(item) => item.column}
            />
            <div className='mt-4 text-right'>
              <Button
                disabled={!selectedParameter || selectedColumnIndex === -1}
                onClick={linkParameter}
              >
                关联
              </Button>
            </div>
          </Col>
          <Col>
            <div>模型参数与设计表列映射</div>
            <ColumnParameterLinkage
              dataSource={linkedColumns}
              selectedColumns={selectedColumns}
              setSelectedColumns={setSelectedColumns}
            />
            <div className='mt-4'>
              <Button
                disabled={!selectedColumns?.length}
                onClick={unlinkParameters}
              >
                取消关联
              </Button>
            </div>
          </Col>
        </Row>
      ),
    },
  ];

  const changeActiveState = async (e: CheckboxChangeEvent) => {
    try {
      await designTableCommands.setDesignTableActivated(
        tableId,
        e.target.checked,
      );
      await docMgr.updateDocumentObjects();
    } catch (err: any) {
      MessageTip.error(err?.message || '激活状态切换失败');
    }
  };

  const openEditor = () => {
    setEditorOpen(true);
  };

  const importFromCsv = async (tableId?: string) => {
    setShowProgress(true);
    setUploadPercent(0);

    return new Promise<void>((resolve, reject) => {
      S3Inst.uploadFile(
        'cad',
        StringUtils.randomString(10) + '.csv',
        fileToImport,
        (progress: { loaded: number; total: number }) => {
          const percentage = Math.floor(
            (progress.loaded * 100) / progress.total,
          );
          setUploadPercent(percentage);
        },
        async (data: { bucket: string; path: string }) => {
          try {
            const bucket = data.bucket;
            const path = data.path;

            const result = await designTableCommands.importDesignTable(
              `s3://${bucket}${path}`,
              tableId,
            );
            if (result?.id) {
              setTableId(result.id);
            }

            setShowProgress(false);
            setUploadPercent(0);
            resolve();
          } catch (err: any) {
            setShowProgress(false);
            setUploadPercent(0);
            MessageTip.error(err?.message || '导入设计表失败');
            reject(err);
          }
        },
      );
    });
  };

  const exportToCsv = async () => {
    if (!FeatureManager.isFeatureEnabled('electron-show-port')) {
      (window as any)?.electronCenter?.emit(
        DESIGN_TABLE_EVENTS.EXPORT_DESIGN_TABLE,
        tableId,
      );
      return;
    }
    try {
      const {
        data: { path, dl },
      } = await httpApi.getExportPath(
        getQueryParam<string>(QueryParamKeys.DOCUMENT_ID),
        'csv',
      );
      await designTableCommands.exportDesignTable(tableId, path);
      const link = document.createElement('a');
      link.href = dl;
      link.click();
    } catch (err: any) {
      MessageTip.error(err?.message || '导出设计表失败');
    }
  };

  const importFile = () => {
    if (!FeatureManager.isFeatureEnabled('electron-show-port')) {
      (window as any)?.electronCenter?.emit(
        DESIGN_TABLE_EVENTS.IMPORT_DESIGN_TABLE,
        tableId,
      );
      return;
    }
    fileInputRef.current?.click();
  };

  const importSelectedFile = (e: ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (file) {
      setFileToImport(file);
      e.target.value = '';
    }
  };

  const onSubmit = async () => {
    if (stage === 'creation') {
      if (mode === 'create') {
        try {
          const result = await designTableCommands.createDesignTable(
            tableName,
            targetKeys.map(
              (key) => parameters.find((p) => p.key === key)?.label,
            ),
            targetKeys as string[],
          );
          if (result) {
            setTableId(result.id);
          }
        } catch (err: any) {
          MessageTip.error(err?.message || '创建设计表失败');
        }
      } else if (mode === 'import' && fileToImport) {
        try {
          await importFromCsv();
        } catch (err: any) {
          // importFromCsv already handles error display
        }
      }
    }
  };

  return (
    <>
      <input
        ref={fileInputRef}
        type='file'
        accept='.csv'
        className='hidden'
        onChange={importSelectedFile}
      />
      <Modal
        open={showProgress}
        footer={null}
        closable={false}
        centered
        maskClosable={false}
      >
        <div style={{ textAlign: 'center', padding: 24 }}>
          <div style={{ marginBottom: 16 }}>文件上传中，请稍候...</div>
          <Progress
            percent={uploadPercent}
            status={uploadPercent < 100 ? 'active' : 'success'}
          />
        </div>
      </Modal>

      <DesignTableEditor
        open={editorOpen}
        setOpen={setEditorOpen}
        tableId={tableId}
        table={designTable}
      />

      <CommandDialog
        onClose={onClose}
        title={title}
        placement='topLeft'
      >
        <div className='mx-6 my-4'>
          <Row
            className='mx-6 w-750px]'
            gutter={[16, 16]}
            align='middle'
          >
            <Col span={6}>
              <label className='mr-2'>名称</label>
            </Col>
            <Col span={designTable ? 12 : 18}>
              <Input
                value={tableName}
                readOnly={stage === 'configuration'}
                onChange={(e) => setTableName(e.target.value)}
              />
            </Col>
            {designTable && (
              <Col
                span={6}
                className='text-right'
              >
                <Checkbox
                  checked={designTable.active}
                  onChange={changeActiveState}
                >
                  激活
                </Checkbox>
              </Col>
            )}
          </Row>
          {stage === 'creation' && (
            <>
              <Radio.Group
                className='my-4'
                value={mode}
                onChange={(e) => setMode(e.target.value)}
              >
                <Radio
                  value='import'
                  className='block mb-2'
                >
                  导入外部文件创建设计表
                </Radio>
                <Radio
                  value='create'
                  className='block mb-2'
                >
                  基于模型参数创建设计表
                </Radio>
              </Radio.Group>

              {loading ? (
                <Spin />
              ) : isImportMode ? (
                <CsvFileImporter
                  onFileSelected={setFileToImport}
                ></CsvFileImporter>
              ) : (
                <ParameterTransfer
                  parameters={parameters}
                  targetKeys={targetKeys}
                  setTargetKeys={setTargetKeys}
                />
              )}
            </>
          )}

          {stage === 'configuration' && (
            <Tabs
              className='h-340px]'
              activeKey={activeTabKey}
              onChange={setActiveTabKey}
              items={tabItems}
            />
          )}
        </div>

        <CommandFormFooter
          isSubmitLoading={false}
          onClose={onClose}
          cancelText={stage === 'creation' ? '取消' : '关闭'}
          onSubmit={onSubmit}
          showSubmit={stage === 'creation'}
          submitText='确定'
          isSubmitDisabled={
            stage === 'creation' && mode === 'import' && !fileToImport
          }
        >
          {stage === 'configuration' && (
            <>
              <Button onClick={openEditor}>编辑设计表</Button>
              <Button onClick={importFile}>导入文件</Button>
              <Button onClick={exportToCsv}>导出文件</Button>
            </>
          )}
        </CommandFormFooter>
      </CommandDialog>
    </>
  );
}

export const cmdDesignTable: CurvedBaseCommand = {
  id: 'CmdDesignTable',
  label: '设计表',
  icon: 'commands/common/design-table',
  create: (label, onClose, props) => (
    <DesignTableCommand
      title={i18n.t(label)}
      onClose={onClose}
      props={props}
    />
  ),
};
